<template>
  <div class="page-wrapper">
    <div class="page-header">
      <span class="text-primary font-bold">流程实例管理</span>
    </div>

    <div class="page-content">
      <!-- 搜索表单 -->
      <el-form :inline="true" :model="searchForm" class="search-form">
        <el-form-item label="流程名称">
          <el-input v-model="searchForm.name" placeholder="请输入流程名称" clearable />
        </el-form-item>
        <el-form-item label="发起人">
          <el-input v-model="searchForm.startUserId" placeholder="请输入发起人" clearable />
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="searchForm.status" placeholder="请选择状态" clearable>
            <el-option
              v-for="item in statusOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleSearch">查询</el-button>
          <el-button @click="resetSearch">重置</el-button>
        </el-form-item>
      </el-form>

      <!-- 表格区域 -->
      <div class="table-wrapper">
        <el-table :data="tableData" v-loading="loading">
          <el-table-column prop="name" label="流程名称" width="150" show-overflow-tooltip />
          <el-table-column prop="processDefinitionKey" label="流程标识" width="150" />
          <el-table-column prop="processDefinitionCategory" label="流程分类" width="100">
            <template #default="{ row }">
              {{ getCategoryName(row.processDefinitionCategory) }}
            </template>
          </el-table-column>
          <el-table-column prop="startUserId" label="发起人" width="150" />
          <el-table-column prop="startTime" label="发起时间" width="180" show-overflow-tooltip />
          <el-table-column prop="endTime" label="结束时间" width="180" show-overflow-tooltip />
          <el-table-column prop="businessStatus" label="状态" width="150">
            <template #default="{ row }">
              <el-tag :type="getStatusType(row.businessStatus)">
                {{ getStatusLabel(row.businessStatus) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作" min-width="200" fixed="right">
            <template #default="{ row }">
              <el-button type="warning" link @click="handleDiagram(row)">流程图</el-button>
              <el-button type="primary" link @click="handleTaskRecord(row)">审批记录</el-button>
              <el-button
                type="danger"
                link
                :disabled="row.businessStatus !== 'running'"
                @click="handleTerminate(row)"
              >
                终止
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>

      <!-- 分页区域 -->
      <div class="pagination-wrapper">
        <el-pagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :page-sizes="[10, 20, 30, 50]"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>

      <!-- 流程图对话框 -->
      <el-dialog v-model="diagramVisible" title="流程图" width="80%" destroy-on-close>
        <ProcessView ref="processViewRef" />
      </el-dialog>

      <!-- 添加审批记录对话框 -->
      <el-dialog
        v-model="taskRecordVisible"
        title="审批记录"
        width="800px"
        :destroy-on-close="true"
        class="task-record-dialog"
      >
        <el-timeline>
          <el-timeline-item
            v-for="task in taskRecords"
            :key="task.id"
            :type="getTimelineItemType(task.status)"
            :timestamp="task.createTime"
          >
            <div class="task-record-item">
              <h4>{{ task.name }}</h4>
              <div class="task-info">
                <span>审批人：{{ task.assignee }}</span>
                <div class="task-status">
                  <el-tag v-if="task.operationType" size="small" type="info" class="operation-type">
                    {{ getOperationTypeLabel(task.operationType) }}
                  </el-tag>
                  <el-tag size="small" :type="getTaskStatusType(task.status)">
                    {{ getTaskStatusLabel(task.status) }}
                  </el-tag>
                </div>
              </div>
              <div v-if="task.reason" class="task-reason">审批意见：{{ task.reason }}</div>
              <div class="task-time">
                <span>开始时间：{{ task.createTime }}</span>
                <span v-if="task.endTime">结束时间：{{ task.endTime }}</span>
                <span v-if="task.durationInMillis">
                  耗时：{{ formatDuration(task.durationInMillis) }}
                </span>
              </div>
            </div>
          </el-timeline-item>
        </el-timeline>
      </el-dialog>
    </div>
  </div>
</template>

<script setup lang="ts" name="ProcessInstance">
import { ref, reactive, onMounted, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { InstanceVo } from '@/types/flow'
import { getProcessInstancePage, stopProcessInstance } from '@/api/flow/instance'
import { useDictOptions } from '@/utils/dict'
import ProcessView from '@/views/ProcessView.vue'
import { getTaskListByProcessInstanceId } from '@/api/flow/task'
import type { TaskVo } from '@/types/flow'

// 搜索表单
const searchForm = reactive({
  name: '',
  startUserId: '',
  status: '',
})

// 获取状态字典选项
const { options: statusOptions } = useDictOptions('biz_status')

// 加载任务状态字典
const { options: taskStatusOptions } = useDictOptions('task_status')

// 加载操作类型字典
const { options: operationTypeOptions } = useDictOptions('task_operation')

// 获取状态标签
const getStatusLabel = (status: string) => {
  const option = statusOptions.value.find((opt) => opt.value === status)
  return option?.label || status
}

// 获取状态标签类型
const getStatusType = (status: string) => {
  const map: Record<string, string> = {
    waiting: 'warning',
    finish: 'success',
    termination: 'danger',
    cancel: 'info',
    back: 'warning',
    invalid: 'info',
    draft: 'info',
  }
  return map[status] || 'info'
}

// 获取状态标签
const getTaskStatusLabel = (status: string) => {
  const option = taskStatusOptions.value.find((opt) => opt.value === status)
  return option?.label || status
}

// 获取状态标签类型
const getTaskStatusType = (status: string) => {
  const map: Record<string, string> = {
    running: 'primary',
    approve: 'success',
    reject: 'danger',
    cancel: 'info',
    return: 'warning',
    approving: 'success',
    waiting: 'warning',
  }
  return map[status] || 'info'
}

// 获取操作类型标签
const getOperationTypeLabel = (type: string) => {
  const option = operationTypeOptions.value.find((opt) => opt.value === type)
  return option?.label || type
}

// 获取流程分类字典选项
const { options: categoryOptions } = useDictOptions('bpmn_category')

// 获取分类名称
const getCategoryName = (code: string) => {
  const option = categoryOptions.value.find((opt) => opt.value === code)
  return option?.label || code
}

// 表格数据
const tableData = ref<InstanceVo[]>([])
const loading = ref(false)
// 流程图相关
const processViewRef = ref()
// 分页
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)

// 审批记录相关
const taskRecordVisible = ref(false)
const taskRecords = ref<TaskVo[]>([])

// 加载表格数据
const loadTableData = async () => {
  loading.value = true
  try {
    const params = {
      pageNo: currentPage.value,
      pageSize: pageSize.value,
      ...searchForm,
    }
    const res = await getProcessInstancePage(params)
    tableData.value = res.data.list
    total.value = res.data.total
  } catch (error) {
    ElMessage.error('获取流程实例列表失败')
  } finally {
    loading.value = false
  }
}

// 搜索
const handleSearch = () => {
  currentPage.value = 1
  loadTableData()
}

// 重置搜索
const resetSearch = () => {
  searchForm.name = ''
  searchForm.startUserId = ''
  searchForm.status = ''
  handleSearch()
}

const diagramVisible = ref(false)
// 查看流程图
const handleDiagram = async (row: InstanceVo) => {
  diagramVisible.value = true
  await nextTick(() => {
    processViewRef.value?.init(row.id)
  })
}

// 查看审批记录
const handleTaskRecord = async (row: any) => {
  try {
    const res = await getTaskListByProcessInstanceId(row.id)
    taskRecords.value = res.data
    taskRecordVisible.value = true
  } catch (error) {
    ElMessage.error('获取审批记录失败')
  }
}

// 获取时间线项目类型
const getTimelineItemType = (status: string) => {
  switch (status) {
    case 'completed':
      return 'success'
    case 'rejected':
      return 'danger'
    case 'running':
      return 'primary'
    default:
      return 'info'
  }
}

// 格式化持续时间
const formatDuration = (duration: number) => {
  const seconds = Math.floor(duration / 1000)
  const minutes = Math.floor(seconds / 60)
  const hours = Math.floor(minutes / 60)
  const days = Math.floor(hours / 24)

  if (days > 0) {
    return `${days}天${hours % 24}小时`
  } else if (hours > 0) {
    return `${hours}小时${minutes % 60}分钟`
  } else if (minutes > 0) {
    return `${minutes}分钟${seconds % 60}秒`
  } else {
    return `${seconds}秒`
  }
}

// 终止实例
const handleTerminate = (row: InstanceVo) => {
  ElMessageBox.confirm('确认终止该流程实例吗？终止后不可恢复', '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(async () => {
      try {
        await stopProcessInstance(row.id)
        ElMessage.success('终止成功')
        // 刷新列表
        loadTableData()
      } catch (error) {
        console.error('终止流程实例失败:', error)
        ElMessage.error('终止流程实例失败')
      }
    })
    .catch(() => {
      // 取消操作，不做处理
    })
}

// 分页处理
const handleSizeChange = (val: number) => {
  pageSize.value = val
  loadTableData()
}

const handleCurrentChange = (val: number) => {
  currentPage.value = val
  loadTableData()
}

// 初始化加载数据
onMounted(() => {
  loadTableData()
})
</script>

<style scoped>
.instance {
  padding: 20px;
}

.search-form {
  margin-bottom: 20px;
}

.pagination {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}

.diagram-container {
  height: 600px;
  width: 100%;
}

/* 添加禁用按钮样式 */
:deep(.el-button.is-disabled) {
  opacity: 0.6;
  cursor: not-allowed;
}

/* 优化按钮间距 */
:deep(.el-button + .el-button) {
  margin-left: 8px;
}

/* 审批记录样式 */
.task-record-dialog {
  :deep(.el-dialog__body) {
    padding: 20px 24px;
    max-height: 600px;
    overflow-y: auto;
  }
}

.task-record-item {
  padding: 12px 16px;
  background: var(--el-fill-color-light);
  border-radius: 8px;
  margin-bottom: 4px;

  h4 {
    margin: 0 0 8px;
    font-size: 15px;
    color: var(--el-text-color-primary);
  }

  .task-info {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
    font-size: 14px;
    color: var(--el-text-color-regular);
  }

  .task-reason {
    margin-bottom: 8px;
    font-size: 14px;
    color: var(--el-text-color-regular);
    line-height: 1.5;
  }

  .task-time {
    display: flex;
    gap: 16px;
    font-size: 13px;
    color: var(--el-text-color-secondary);
  }
}

.task-status {
  display: flex;
  align-items: center;
  gap: 8px;
}

.operation-type {
  --el-tag-bg-color: var(--el-fill-color-dark);
  --el-tag-border-color: var(--el-border-color-darker);
}
</style>
